import { ACSubscriber } from './ACSubscriber';
import { ACSubscriberHolder } from './ACSubscriberHolder';

export class ACPublisher<T> {

  protected subscriber?: WeakRef<ACSubscriber<T>>;
  protected timeoutId?: number;

  subscribeValue(callback: (value: T) => void): ACSubscriberHolder {
    let subscriber = new ACSubscriber<T>(callback);
    this.subscriber = new WeakRef(subscriber);
    return new ACSubscriberHolder(this, subscriber);
  }

  timeout(callback: () => void, milliseconds: number): ACPublisher<T> {
    this.timeoutId = setTimeout(() => {
      callback();
      this.cancelSubscribe();
    }, milliseconds);

    return this;
  }

  sendValue(value: T) {
    this.subscriber?.deref()?.sendValue(value);
    clearTimeout(this.timeoutId);
    this.timeoutId = undefined;
  }

  cancelSubscribe() {
    this.subscriber = undefined;
  }

  isValid(): boolean {
    return (this.subscriber?.deref() != undefined);
  }

}


export class ACCurrentValuePublisher<T> extends ACPublisher<T> {
  cachedValue: T;
  _dropFirst: boolean = false;
  constructor(initValue: T) {
    super();
    this.cachedValue = initValue;
  }

  dropFirst(): ACCurrentValuePublisher<T> {
    this._dropFirst = true;
    return this;
  }

  subscribeValue(callback: (value: T) => void): ACSubscriberHolder {
    let holder = super.subscribeValue(callback);
    if (!this._dropFirst) {
      callback(this.cachedValue);
    }
    return holder;
  }

  sendValue(value: T) {
    super.sendValue(value);
    this.cachedValue = value;
  }

}
